package com.mengxuegu.workflow;

import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.File;
import java.io.FileInputStream;
import java.util.zip.ZipInputStream;


/**
 * activiti的部署由RepositoryService负责，而RepositoryService则委托DeploymentBuilder进行部署。
 * 这里使用了建造者模式。通过源码分析可知DeploymentBuilder为流程部署的实体DeploymentEntity进行属性设置，
 * 然后再调用deploy进行部署。
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class ActivitiTest03Deployment {

    @Autowired
    RepositoryService repositoryService;

    /**
     * 通过 .zip 流程压缩包进行部署的流程定义
     * <p>
     * 部署流程定义涉及表：
     * ACT_RE_PROCDEF 新增数据: 流程定义数据
     * ACT_RE_DEPLOYMENT 新增数据: 流程部署数据
     * ACT_GE_BYTEARRAY 新增数据：将当前流程图绑定到此流程定义部署数据上
     */
    @Test
    public void deployByZip() throws Exception {
        File file = new File("D:/请假流程模型.leaveProcess.zip");
        String filename = file.getName();
        // 压缩包输入流
        ZipInputStream zipis = new ZipInputStream(new FileInputStream(file));
        // 创建部署实例 
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
        // 添加zip流 
        deploymentBuilder.addZipInputStream(zipis);
        // 部署名称 
        deploymentBuilder.name(filename.substring(0, filename.indexOf(".")));
        // 执行部署流程定义
        deploymentBuilder.deploy();
        System.out.println("zip压缩包方式部署流程定义完成");
    }

    /**
     * 通过 .bpmn 或 .bpmn20.xml 流程文件进行部署的流程定义
     * <p>
     * 缺陷：没有png流程图
     */
    @Test
    public void deployByBpmnFile() throws Exception {
        // .bpmn 文件
        File file = new File("D:/leave.bpmn");
        // .bpmn20.xml 文件
        //File file = new File("D:/请假流程模型.bpmn20.xml");
        String filename = file.getName();
        // 输入流
        FileInputStream input = new FileInputStream(file);
        // 创建部署实例
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
        // .bpmn20.xml 或 .bpmn (activiti5.10版本以上支持)
        // addInputStream 的第一个参数，后缀名必须是bpmn或bpmn20.xml，
        // 否则流程引擎不会对其进行解析，部署之后不会生成流程实例，就无法进行流程的启动等操作。
        deploymentBuilder.addInputStream(filename, input);
        // 部署名称
        //deploymentBuilder.name(filename.substring(0, filename.indexOf(".")));
        // 执行流程定义部署
        deploymentBuilder.deploy();
        System.out.println("通过 .bpmn 或 .bpmn20.xml 部署完成");
    }

    /**
     * 根据部署ID删除流程定义部署信息：
     * ACT_GE_BYTEARRAY、
     * ACT_RE_DEPLOYMENT、
     * ACT_RU_IDENTITYLINK、
     * ACT_RE_PROCDEF、
     * ACT_RU_EVENT_SUBSCR
     */
    @Test
    public void delete() {
        try {
            // 部署ID
            String deploymentId = "9a14702d-c996-11eb-8eef-02466359b284";
            // 不带级联的删除：如果有正在执行的流程，则删除失败抛出异常；不会删除 ACT_HI_和 历史表数据
            repositoryService.deleteDeployment(deploymentId);
            // 级联删除：不管流程是否启动，都能可以删除；并删除历史表数据。
            //repositoryService.deleteDeployment(deploymentId, true);
            System.out.println("删除流程定义部署信息成功");
        } catch (Exception e) {
            e.printStackTrace();
            if (e.getMessage().indexOf("a foreign key constraint fails") > 0) {
                System.out.println("有正在执行的流程，不允许删除");
            } else {
                System.out.println("删除失败，原因：" + e.getMessage());
            }
        }
    }

}
